(Zhu et al. 2008) (Xie 2023) (Robinson, McCarthy, and Smyth 2010) (Morgan 2022) (Durinck et al. 2009) (Gu et al. 2014) (Gu, Eils, and Schlesner 2016) (Wickham 2016) (Slowikowski 2023) (Raudvere et al. 2019)

if (!requireNamespace("GEOmetadb", quietly = TRUE))
  BiocManager::install("GEOmetadb")

if (!requireNamespace("knitr", quietly = TRUE))
  install.packages("knitr")

if (!require("edgeR", quietly = TRUE))
  BiocManager::install("edgeR")

if (!requireNamespace("BiocManager", quietly = TRUE))
  install.packages("BiocManager")

if (!requireNamespace("biomaRt", quietly = TRUE))
  BiocManager::install("biomaRt")

if (!requireNamespace("ComplexHeatmap", quietly = TRUE))
  BiocManager::install("ComplexHeatmap")

if (!requireNamespace("circlize", quietly = TRUE))
  BiocManager::install("circlize")

if (!requireNamespace("ggplot2", quietly = TRUE))
  install.packages("ggplot2")

if (!requireNamespace("ggrepel", quietly = TRUE))
  install.packages("ggrepel")

Calling required packages

library(BiocManager)
library(GEOmetadb)
library(knitr)
library(edgeR)
library(biomaRt)
library(ComplexHeatmap)
library(circlize)
library(ggplot2)
library(ggrepel)

Download the data

GSE152074 raw data supplemntary file downloaded

sfiles = getGEOSuppFiles('GSE152075')
fnames = rownames(sfiles)
# there is only one supplemental file
readData = read.table(fnames[1],header=TRUE, check.names = TRUE)

Data

Data from (Lieberman et al. 2020).

kable(readData[1:5, 1:5], type = "html", row.names = TRUE)

Table 1: Original data contains HGNC annotation as row names. Column names have prefixes before their identifier number as either POS or NEG. Corresponding to either positive for COVID19 or negative.

Assess

Add 1 to all values of data so later on when conducting log2(cpm) we can avoid negative infinity values. (Advised by Professor Isserlin)

readData <- readData + 1

Setting first column as gene id for future format purposes

#Place rownames in first column for future format purposes
inter <- data.frame("HUGO" = rownames(readData))
geneData <- cbind(inter$HUGO, readData)
colnames(geneData)[1] <- "HUGO"

Clean

Remove any outliers that does not have at least 2 read per million in n of the samples. We set this as 2 since we add 1 to all of our dataset in the beginning of the code to have better plots. Denoting n as the smallest group of replicates which is the control group of 53. Using n = 53 conduct the removal of low counts.

#translate out counts into counts per millison using 
#the edgeR package function cpm
cpms = cpm(geneData[,2:485])
rownames(cpms) <- geneData[,1]
# get rid of low counts
keep = rowSums(cpms >2) >=53
geneData_exp_filtered = geneData[keep,]

Remove version numbers if they exists on gene id(HUGO) column. This makes it easier for mapping later on.

geneData_exp_filtered[,1] <- gsub("\\.[0-9]", "", geneData_exp_filtered[,1])

Map

#Mapping the name using biomatr
# list available gene annotation databases
bio <- useMart("ensembl", dataset = "hsapiens_gene_ensembl")
conversion_stash <- "geneMapping.rds"
if(file.exists(conversion_stash)){
  geneMapping <- readRDS(conversion_stash)
} else{
# convert column of gene IDs to Hugo symbols
geneMapping <- getBM(attributes = c("ensembl_gene_id", "hgnc_symbol"),
                     mart = bio,
                     filters = "hgnc_symbol",
                     values = geneData_exp_filtered[,1])
saveRDS(geneMapping, conversion_stash)
}

Combine the mapped gene data to original data

#Merge the data
mergedData <- merge(geneData_exp_filtered, geneMapping, by.x = 1, by.y = 2)
#remove duplicate rows in the gene data
mergedDataNoDup <- mergedData[!duplicated(mergedData[,1:485]),]

Apply Normalization

Randomly sample data to reduce the size of sample. Original sample is too large leading to computation errors due to the limitation of author’s computer.


set.seed(12345)
randomSamplePOS <- sample(mergedDataNoDup[2:431], 25)
randomSampleNEG <- sample(mergedDataNoDup[432:485], 25)
randomSample <- cbind(randomSamplePOS,randomSampleNEG, mergedDataNoDup$ensembl_gene_id, mergedDataNoDup$HUGO)

Define groups to use in normalization


samples <- data.frame(lapply(colnames(randomSample[1:50]), 
        FUN=function(x){unlist(strsplit(x, 
                        split = "_"))[c(2,1)]}))
colnames(samples) <- colnames(randomSample[1:50])
rownames(samples) <- c("patients","cell_type")
samples <- data.frame(t(samples))

Applying TMM to data


filtered_data_matrix <- as.matrix(randomSample[1:50])
rownames(filtered_data_matrix) <- randomSample$`mergedDataNoDup$ensembl_gene_id`
d = DGEList(counts=filtered_data_matrix, group=samples$cell_type)

d = calcNormFactors(d)

normalized_counts <- cpm(d)
#add columns of ensembl and hgnc id

normalized_count_data = data.frame(normalized_counts)
normalized_count_data$ensembl_gene_id <- mergedDataNoDup$ensembl_gene_id
normalized_count_data$hgnc_symbol <- mergedDataNoDup$HUGO


#This is a duplicate ensembl id that is giving errors when running code.
normalized_count_data <- normalized_count_data[-c(1902),]
model_design <- model.matrix(~samples$cell_type+0)
d <- estimateDisp(d, model_design)

Differential Gene Expression

LIMMA

p-value calculation using LIMMA

model_design <- model.matrix(~ samples$cell_type )

expressionMatrix <- as.matrix(normalized_count_data[,1:50])
rownames(expressionMatrix) <- 
  normalized_count_data$ensembl_gene_id
colnames(expressionMatrix) <- 
  colnames(normalized_count_data)[1:50]
minimalSet <- ExpressionSet(assayData=expressionMatrix)

Taking into account Patient variability

model_design_pat <- model.matrix(
  ~ samples$patients + samples$cell_type)
fit_pat <- lmFit(minimalSet, model_design_pat)
fit2_pat <- eBayes(fit_pat,trend=TRUE)

topfit_pat <- topTable(fit2_pat, 
                   coef=ncol(model_design_pat),
                   adjust.method = "BH",
                   number = nrow(expressionMatrix))
#merge hgnc names to topfit table
output_hits_pat <- merge(normalized_count_data[,51:52],
                         topfit_pat,by.y=0,by.x=1,all.y=TRUE)
#sort by pvalue
output_hits_pat <- output_hits_pat[order(output_hits_pat$P.Value),]
length(which(output_hits_pat$P.Value < 0.05))
length(which(output_hits_pat$adj.P.Val < 0.05))

QLF

d = DGEList(counts=filtered_data_matrix, group=samples$cell_type)
d <- estimateDisp(d, model_design_pat)
fit <- glmQLFit(d, model_design_pat)
qlf.pos_vs_neg <- glmQLFTest(fit, coef='samples$cell_typePOS')
kable(topTags(qlf.pos_vs_neg), type="html",row.names = FALSE)

P-values were corrected using Quasilikelihood method. Quasilikelihood is better becacuse it is tailored towards RNAseq data

qlf_output_hits <- topTags(qlf.pos_vs_neg,sort.by = "PValue",
                           n = nrow(normalized_count_data))
length(which(qlf_output_hits$table$PValue < 0.05))
length(which(qlf_output_hits$table$FDR < 0.05))

Thresholded over-representation analysis

Write to file upregulated, and downregulated genes

Which ones are upregulated and downregulated

length(which(qlf_output_hits$table$PValue < 0.05 
             & qlf_output_hits$table$logFC > 0))

length(which(qlf_output_hits$table$PValue < 0.05 
             & qlf_output_hits$table$logFC < 0))
qlf_output_hits_withgn <- merge(randomSample[,51:52],qlf_output_hits, by.x=1, by.y = 0)
#number higher the lower the pvalue, and if it is upregulated number is positive, and negative for downregulated
qlf_output_hits_withgn[,"rank"] <- -log(qlf_output_hits_withgn$PValue,base =10) * sign(qlf_output_hits_withgn$logFC)
qlf_output_hits_withgn <- qlf_output_hits_withgn[order(qlf_output_hits_withgn$rank),]
upregulated_genes <- qlf_output_hits_withgn$`mergedDataNoDup$HUGO`[
  which(qlf_output_hits_withgn$PValue < 0.05 
             & qlf_output_hits_withgn$logFC > 0)]
downregulated_genes <- qlf_output_hits_withgn$`mergedDataNoDup$HUGO`[
  which(qlf_output_hits_withgn$PValue < 0.05 
             & qlf_output_hits_withgn$logFC < 0)]
write.table(x=upregulated_genes,
            file=file.path("data","upregulated_genes.txt"),sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)
write.table(x=downregulated_genes,
            file=file.path("data","downregulated_genes.txt"),sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)
write.table(x=data.frame(genename= qlf_output_hits_withgn$`mergedDataNoDup$HUGO`,F_stat= qlf_output_hits_withgn$rank),
            file=file.path("data","ranked_genelist.txt"),sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)

Non-thresholded Gene set Enrichment Analysis

gmt_url = "http://download.baderlab.org/EM_Genesets/current_release/Human/symbol/"
# list all the files on the server
filenames = RCurl::getURL(gmt_url)
tc = textConnection(filenames)
contents = readLines(tc)
close(tc)
# get the gmt that has all the pathways and does not include terms inferred
# from electronic annotations(IEA) start with gmt file that has pathways only
rx = gregexpr("(?<=<a href=\")(.*.GOBP_AllPathways_no_GO_iea.*.)(.gmt)(?=\">)", contents,
    perl = TRUE)
gmt_file = unlist(regmatches(contents, rx))
dest_gmt_file <- file.path(data_dir, gmt_file)
download.file(paste(gmt_url, gmt_file, sep = ""), "bader_lab.gmt")

Conduct non-thresholded gene set enrichment analysis using the ranked set of genes from Assignment #2.

  1. What method did you use? What genesets did you use? Make sure to specify versions and cite your methods. I used the GSEA desktop application to run GSEA Subramanian, Tamayo, et al. (2005, PNAS) and Mootha, Lindgren, et al. (2003, Nature Genetics). I used the genesets from the bader lab extracted from the code above I used. Or it can be retrieved from here http://download.baderlab.org/EM_Genesets/current_release/Human/symbol/.
  2. Summarize your enrichment results. SARs-CoV-2 positive samples: 4965 / 6074 gene sets are upregulated in phenotype na_pos 442 gene sets are significant at FDR < 25% 410 gene sets are significantly enriched at nominal pvalue < 1% 662 gene sets are significantly enriched at nominal pvalue < 5% Top gene-set: HALLMARK_INTERFERON_ALPHA_RESPONSE%MSIGDBHALLMARK%HALLMARK_INTERFERON_ALPHA_RESPONSE Number of genes in leading edge: 80 Top gene associated: CXCL11

SARs-CoV-2 negative samples: 1109 / 6074 gene sets are upregulated in phenotype na_neg 274 gene sets are significantly enriched at FDR < 25% 196 gene sets are significantly enriched at nominal pvalue < 1% 276 gene sets are significantly enriched at nominal pvalue < 5% Top gene-set: ENERGY DERIVATION BY OXIDATION OF ORGANIC COMPOUNDS%GOBP%GO:0015980 Number of genes in leading edge: 165 Top gene associated: TEFM 3. How do these results compare to the results from the thresholded analysis in Assignment #2. Compare qualitatively. Is this a straight forward comparison? Why or why not? For the upregulated genes the top results are negative regulation of viral genome replication, negative regulation of viral process, response to type II interferon. downregulated we got cytoplasmic translation, positive regulation of respiratory burst, and intermediate filament-based process. I had too many genes so I couldn’t run all the genes at once for my whole list. For upregulated in thresholded and non-thresholded they align a bit together by having interferon related pathway results. Other then that they don’t seem to be similar. A common pathway in downregulated and and all of the genes for thresholded was a pathway related to cytoplasmic. However in non thresholded there were cytoplasmic related pathways but were very low in the list. It is not a straight forward comparison they both have different values as analysis. The thresholed could be more sensitive while the non-thresholded be more general.

Using your results from your non-thresholded gene set enrichment analysis visualize your results in Cytoscape.

red - upregulated from neg to pos, blue - downregulated in positive covid19 patietns compared to negative patients. ranked list = depending on the expression of a gene in pos compared to neg

1.

Create an enrichment map - how many nodes and how many edges in the resulting map?

379 Nodes 1511 Edges

What thresholds were used to create this map?

FDR q-value cutoff: 0.1 Analysis Type: GSEA Node cutoff: 0.1 Edge cutoff: 0.375

Make sure to record all thresholds. Include a screenshot of your network prior to manual layout.

Figure: Screenshot of network prior to manual layout

2. Annotate your network - what parameters did you use to annotate the network. If you are using the default parameters make sure to list them as well.

Used the auto annotate application in cytoscape. Cluster algorithm: MCL Cluster Label Column: GS_DESCR Label Algorithm: WordCloud: Adjacent Words(default) Max words per label: 3 Minimum word occurrence: 1 Adjacent word bonus: 8 Border Width: 3 Opacity: 20% Font Scale: 20%

Figure: Annotated network

3. Make a publication ready figure - include this figure with proper legends in your notebook.

4. Collapse your network to a theme network. What are the major themes present in this analysis? Do they fit with the model? Are there any novel pathways or themes?

Figure: Collapsed Major themes present: Upregulated: - GPCRS Rhodopsin ligand - Chemokine Migration chemotaxis - Cellular response necrosis - type II interferon - Migration monocyte chemotaxis - Surface receptor pattern

Downregulated: - gluconeogenesis glycolysis - superpathway warburg effect - srp protein synthesis

Present your results with the use of tables and screenshots. All figures should have appropriate figure legends.

If using figures create a figures directory in your repo and make sure all references to the figures are relative in your Rmarkdown notebook.

The most important aspect of the analysis is relating your results back to the initial data and question.

  1. Do the enrichment results support conclusions or mechanism discussed in the original paper? How do these results differ from the results you got from Assignment #2 thresholded methods. 

This is a quotation taken from the original paper “SARS-CoV-2 induced a strong antiviral response with up-regulation of antiviral factors such as OAS1-3 and IFIT1-3 and T helper type 1 (Th1) chemokines CXCL9/10/11, as well as a reduction in transcription of ribosomal proteins” (Lieberman et al. 2020). They have found up-regulation in number of genes. The largest collapsed theme with 729 genes the GPCRS Rhodopsin ligand has two very large pathways named the GPCR ligand binding, and the CLASS A 1 (RHODOPSIN-LIKE RECEPTORS). Both of these gene-sets have at the top of their leading edge the CXCL 10/11/13 similar to the paper where they had up-regulation in the CXCL 9/10/11. In this sense the enrichment results support conclusions made in the original paper. Another example is the chemokine migration chemotaxis. In this major theme there are gene-sets involved in pathways such as the response to type II interferon, cellular response to type II interferon, . In the original paper they mention that as viral load increased the expression of interferon-responsive genes went up. Both of the two themes mentioned are up-regulated gene-sets. It seems that the enrichment results support the conclusion in the original paper.   Comparing from A2 threshold methods in the upregulated analysis for GO using g:profiler we also had results such as response to type II interferon, and cellular response to type II interferon. However we do not see a lot of gene-sets in the up-regulated section for chemokine related pathways.  

For down regulated gene-sets for our network results from GSEA shows a major theme called srp protein synthesis. In this we have genesets such as the cytoplasmic translation. This gene-set is the largest gene-set inside srp protein synthesis and it is also the top result for down regulated genes gene-set for g:profiler using GO annotation. There are evident similarities but looking at the rest of the graph each analysis give results that each other do not have.  

  1. Can you find evidence, i.e. publications, to support some of the results that you see. How does this evidence support your result? In a paper they state that SARS-CoV-2 infected thyroid gland activated the interferon pathways aligning with our results in the upregulation. (Poma et al. 2021)

Using your networks and results from the previous section add one of the following: 1. Add a post analysis to your main network using specific transcription factors, microRNAs or drugs. Include the reason why you chose the specific miRs, TFs or drugs (i.e publications indicating that they might be related to your model). What does this post analysis show? 2, Choose a specific pathway or theme to investigate in more detail. Why did you choose this pathway or theme? Show the pathway or theme as a gene network or as a pathway diagram. Annotate the network or pathway with your original log fold expression values and p-values to show how it is effected in your model. (Hint: if the theme or pathway is not from database that has detailed mechanistic information like Reactome you can use apps like GeneMANIA or String to build the the interaction network.) 3. Sometimes the most interesting information is the gene that has no information. In this type of pathway analysis we can only discover what we have already described previously in the literature or pathway databases. Often pathways found in one disease are applicable to other diseases so this technique can be very helpful. It is important to highlight any genes that are significantly differentially expressed in your model but are not annotated to any pathways. We refer to this set of genes as the dark matter. Include a heatmap of any significant genes that are not annotated to any of the pathways returned in the enrichment analysis. Include a heatmap of any significant genes that are not annotated to any pathways in entire set of pathways used for the analysis.

#References

Durinck, Steffen, Paul T. Spellman, Ewan Birney, and Wolfgang Huber. 2009. “Mapping Identifiers for the Integration of Genomic Datasets with the r/Bioconductor Package biomaRt.” Nature Protocols 4: 1184–91.
Gu, Zuguang, Roland Eils, and Matthias Schlesner. 2016. “Complex Heatmaps Reveal Patterns and Correlations in Multidimensional Genomic Data.” Bioinformatics. https://doi.org/10.1093/bioinformatics/btw313.
Gu, Zuguang, Lei Gu, Roland Eils, Matthias Schlesner, and Benedikt Brors. 2014. “Circlize Implements and Enhances Circular Visualization in r.” Bioinformatics 30: 2811–12.
Lieberman, Nicole AP, Vikas Peddu, Hong Xie, Lasata Shrestha, Meei-Li Huang, Megan C Mears, Maria N Cajimat, et al. 2020. “In Vivo Antiviral Host Transcriptional Response to SARS-CoV-2 by Viral Load, Sex, and Age.” PLoS Biology 18 (9): e3000849.
Morgan, Martin. 2022. BiocManager: Access the Bioconductor Project Package Repository. https://CRAN.R-project.org/package=BiocManager.
Poma, Anna Maria, Alessandro Basolo, Daniele Bonuccelli, Agnese Proietti, Elena Macerola, Clara Ugolini, Ludovica Torregrossa, et al. 2021. “Activation of Type i and Type II Interferon Signaling in SARS-CoV-2-Positive Thyroid Tissue of Patients Dying from COVID-19.” Thyroid : Official Journal of the American Thyroid Association 31 (12): 1766–75. https://doi.org/10.1089/thy.2021.0345.
Raudvere, Uku, Liis Kolberg, Ivan Kuzmin, Tambet Arak, Priit Adler, Hedi Peterson, and Jaak Vilo. 2019. “G:profiler: A Web Server for Functional Enrichment Analysis and Conversions of Gene Lists.” Nucleic Acids Research. https://doi.org/10.1093/nar/gkz369.
Robinson, Mark D, Davis J McCarthy, and Gordon K Smyth. 2010. “edgeR: A Bioconductor Package for Differential Expression Analysis of Digital Gene Expression Data.” Bioinformatics 26 (1): 139–40. https://doi.org/10.1093/bioinformatics/btp616.
Slowikowski, Kamil. 2023. Ggrepel: Automatically Position Non-Overlapping Text Labels with ’Ggplot2’. https://CRAN.R-project.org/package=ggrepel.
Wickham, Hadley. 2016. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org.
Xie, Yihui. 2023. Knitr: A General-Purpose Package for Dynamic Report Generation in r. https://yihui.org/knitr/.
Zhu, Yuelin, Sean Davis, Robert Stephens, Paul S. Meltzer, and Yidong Chen. 2008. “GEOmetadb: Powerful Alternative Search Engine for the Gene Expression Omnibus.” Bioinformatics (Oxford, England) 24 (23): 2798–2800. https://doi.org/10.1093/bioinformatics/btn520.
LS0tDQp0aXRsZTogIkEzIg0KYXV0aG9yOiBKYWUgSHl1bmcgSnVuZw0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnMicNCiAgICBkZl9wcmludDogcGFnZWQNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogMg0KYmlibGlvZ3JhcGh5OiAnQTIuYmliJw0KLS0tDQoNCg0KW0BnZW9tZXRhZGJdDQpbQGtuaXRyXQ0KW0BlZGdlcl0NCltAYmlvY21hbmFnZXJdDQpbQGJpb21hcnRdDQpbQGNpcmNsaXplXQ0KW0Bjb21wbGV4XQ0KW0BnZ3Bsb3QyXQ0KW0BnZ3JlcGVsXQ0KW0BncHJvZmlsZV0NCmBgYHtyLCBtZXNzYWdlPSBGQUxTRX0NCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiR0VPbWV0YWRiIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiR0VPbWV0YWRiIikNCg0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJrbml0ciIsIHF1aWV0bHkgPSBUUlVFKSkNCiAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KDQppZiAoIXJlcXVpcmUoImVkZ2VSIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiZWRnZVIiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBpbnN0YWxsLnBhY2thZ2VzKCJCaW9jTWFuYWdlciIpDQoNCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiYmlvbWFSdCIsIHF1aWV0bHkgPSBUUlVFKSkNCiAgQmlvY01hbmFnZXI6Omluc3RhbGwoImJpb21hUnQiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkNvbXBsZXhIZWF0bWFwIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiQ29tcGxleEhlYXRtYXAiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImNpcmNsaXplIiwgcXVpZXRseSA9IFRSVUUpKQ0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiY2lyY2xpemUiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImdncGxvdDIiLCBxdWlldGx5ID0gVFJVRSkpDQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImdncmVwZWwiLCBxdWlldGx5ID0gVFJVRSkpDQogIGluc3RhbGwucGFja2FnZXMoImdncmVwZWwiKQ0KDQpgYGANCg0KIyMgQ2FsbGluZyByZXF1aXJlZCBwYWNrYWdlcw0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoQmlvY01hbmFnZXIpDQpsaWJyYXJ5KEdFT21ldGFkYikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGVkZ2VSKQ0KbGlicmFyeShiaW9tYVJ0KQ0KbGlicmFyeShDb21wbGV4SGVhdG1hcCkNCmxpYnJhcnkoY2lyY2xpemUpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdncmVwZWwpDQpgYGANCg0KIyMgRG93bmxvYWQgdGhlIGRhdGENCiMjIyBHU0UxNTIwNzQgcmF3IGRhdGEgc3VwcGxlbW50YXJ5IGZpbGUgZG93bmxvYWRlZA0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCnNmaWxlcyA9IGdldEdFT1N1cHBGaWxlcygnR1NFMTUyMDc1JykNCmZuYW1lcyA9IHJvd25hbWVzKHNmaWxlcykNCiMgdGhlcmUgaXMgb25seSBvbmUgc3VwcGxlbWVudGFsIGZpbGUNCnJlYWREYXRhID0gcmVhZC50YWJsZShmbmFtZXNbMV0saGVhZGVyPVRSVUUsIGNoZWNrLm5hbWVzID0gVFJVRSkNCmBgYA0KIyMgRGF0YQ0KDQogRGF0YSBmcm9tIFtAbGllYmVybWFuMjAyMHZpdm9dLg0KYGBge3J9DQprYWJsZShyZWFkRGF0YVsxOjUsIDE6NV0sIHR5cGUgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IFRSVUUpDQpgYGANCg0KIFRhYmxlIDE6IE9yaWdpbmFsIGRhdGEgY29udGFpbnMgSEdOQyBhbm5vdGF0aW9uIGFzIHJvdyBuYW1lcy4gQ29sdW1uIG5hbWVzIGhhdmUgcHJlZml4ZXMgYmVmb3JlIHRoZWlyIGlkZW50aWZpZXIgbnVtYmVyIGFzIGVpdGhlciBQT1Mgb3IgTkVHLiBDb3JyZXNwb25kaW5nIHRvIGVpdGhlciBwb3NpdGl2ZSBmb3IgQ09WSUQxOSBvciBuZWdhdGl2ZS4NCg0KDQoNCiMjIEFzc2Vzcw0KDQpBZGQgMSB0byBhbGwgdmFsdWVzIG9mIGRhdGEgc28gbGF0ZXIgb24gd2hlbiBjb25kdWN0aW5nIGxvZzIoY3BtKSB3ZSBjYW4gYXZvaWQgbmVnYXRpdmUgaW5maW5pdHkgdmFsdWVzLiAoQWR2aXNlZCBieSBQcm9mZXNzb3IgSXNzZXJsaW4pDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCnJlYWREYXRhIDwtIHJlYWREYXRhICsgMQ0KYGBgDQoNCg0KU2V0dGluZyBmaXJzdCBjb2x1bW4gYXMgZ2VuZSBpZCBmb3IgZnV0dXJlIGZvcm1hdCBwdXJwb3Nlcw0KYGBge3J9DQojUGxhY2Ugcm93bmFtZXMgaW4gZmlyc3QgY29sdW1uIGZvciBmdXR1cmUgZm9ybWF0IHB1cnBvc2VzDQppbnRlciA8LSBkYXRhLmZyYW1lKCJIVUdPIiA9IHJvd25hbWVzKHJlYWREYXRhKSkNCmdlbmVEYXRhIDwtIGNiaW5kKGludGVyJEhVR08sIHJlYWREYXRhKQ0KY29sbmFtZXMoZ2VuZURhdGEpWzFdIDwtICJIVUdPIg0KYGBgDQoNCiMjIENsZWFuDQpSZW1vdmUgYW55IG91dGxpZXJzIHRoYXQgZG9lcyBub3QgaGF2ZSBhdCBsZWFzdCAyIHJlYWQgcGVyIG1pbGxpb24gaW4gbiBvZiB0aGUgc2FtcGxlcy4NCldlIHNldCB0aGlzIGFzIDIgc2luY2Ugd2UgYWRkIDEgdG8gYWxsIG9mIG91ciBkYXRhc2V0IGluIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGNvZGUgdG8gaGF2ZSBiZXR0ZXIgcGxvdHMuDQpEZW5vdGluZyBuIGFzIHRoZSBzbWFsbGVzdCBncm91cCBvZiByZXBsaWNhdGVzIHdoaWNoIGlzIHRoZSBjb250cm9sIGdyb3VwIG9mIDUzLg0KVXNpbmcgbiA9IDUzIGNvbmR1Y3QgdGhlIHJlbW92YWwgb2YgbG93IGNvdW50cy4NCmBgYHtyfQ0KI3RyYW5zbGF0ZSBvdXQgY291bnRzIGludG8gY291bnRzIHBlciBtaWxsaXNvbiB1c2luZyANCiN0aGUgZWRnZVIgcGFja2FnZSBmdW5jdGlvbiBjcG0NCmNwbXMgPSBjcG0oZ2VuZURhdGFbLDI6NDg1XSkNCnJvd25hbWVzKGNwbXMpIDwtIGdlbmVEYXRhWywxXQ0KIyBnZXQgcmlkIG9mIGxvdyBjb3VudHMNCmtlZXAgPSByb3dTdW1zKGNwbXMgPjIpID49NTMNCmdlbmVEYXRhX2V4cF9maWx0ZXJlZCA9IGdlbmVEYXRhW2tlZXAsXQ0KYGBgDQoNClJlbW92ZSB2ZXJzaW9uIG51bWJlcnMgaWYgdGhleSBleGlzdHMgb24gZ2VuZSBpZChIVUdPKSBjb2x1bW4uDQpUaGlzIG1ha2VzIGl0IGVhc2llciBmb3IgbWFwcGluZyBsYXRlciBvbi4NCmBgYHtyfQ0KZ2VuZURhdGFfZXhwX2ZpbHRlcmVkWywxXSA8LSBnc3ViKCJcXC5bMC05XSIsICIiLCBnZW5lRGF0YV9leHBfZmlsdGVyZWRbLDFdKQ0KYGBgDQoNCiMjIE1hcA0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQojTWFwcGluZyB0aGUgbmFtZSB1c2luZyBiaW9tYXRyDQojIGxpc3QgYXZhaWxhYmxlIGdlbmUgYW5ub3RhdGlvbiBkYXRhYmFzZXMNCmJpbyA8LSB1c2VNYXJ0KCJlbnNlbWJsIiwgZGF0YXNldCA9ICJoc2FwaWVuc19nZW5lX2Vuc2VtYmwiKQ0KY29udmVyc2lvbl9zdGFzaCA8LSAiZ2VuZU1hcHBpbmcucmRzIg0KaWYoZmlsZS5leGlzdHMoY29udmVyc2lvbl9zdGFzaCkpew0KICBnZW5lTWFwcGluZyA8LSByZWFkUkRTKGNvbnZlcnNpb25fc3Rhc2gpDQp9IGVsc2V7DQojIGNvbnZlcnQgY29sdW1uIG9mIGdlbmUgSURzIHRvIEh1Z28gc3ltYm9scw0KZ2VuZU1hcHBpbmcgPC0gZ2V0Qk0oYXR0cmlidXRlcyA9IGMoImVuc2VtYmxfZ2VuZV9pZCIsICJoZ25jX3N5bWJvbCIpLA0KICAgICAgICAgICAgICAgICAgICAgbWFydCA9IGJpbywNCiAgICAgICAgICAgICAgICAgICAgIGZpbHRlcnMgPSAiaGduY19zeW1ib2wiLA0KICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gZ2VuZURhdGFfZXhwX2ZpbHRlcmVkWywxXSkNCnNhdmVSRFMoZ2VuZU1hcHBpbmcsIGNvbnZlcnNpb25fc3Rhc2gpDQp9DQpgYGANCg0KQ29tYmluZSB0aGUgbWFwcGVkIGdlbmUgZGF0YSB0byBvcmlnaW5hbCBkYXRhDQpgYGB7cn0NCiNNZXJnZSB0aGUgZGF0YQ0KbWVyZ2VkRGF0YSA8LSBtZXJnZShnZW5lRGF0YV9leHBfZmlsdGVyZWQsIGdlbmVNYXBwaW5nLCBieS54ID0gMSwgYnkueSA9IDIpDQojcmVtb3ZlIGR1cGxpY2F0ZSByb3dzIGluIHRoZSBnZW5lIGRhdGENCm1lcmdlZERhdGFOb0R1cCA8LSBtZXJnZWREYXRhWyFkdXBsaWNhdGVkKG1lcmdlZERhdGFbLDE6NDg1XSksXQ0KDQpgYGANCg0KIyMgQXBwbHkgTm9ybWFsaXphdGlvbg0KUmFuZG9tbHkgc2FtcGxlIGRhdGEgdG8gcmVkdWNlIHRoZSBzaXplIG9mIHNhbXBsZS4gT3JpZ2luYWwgc2FtcGxlIGlzIHRvbyBsYXJnZQ0KbGVhZGluZyB0byBjb21wdXRhdGlvbiBlcnJvcnMgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIGF1dGhvcidzIGNvbXB1dGVyLg0KYGBge3J9DQoNCnNldC5zZWVkKDEyMzQ1KQ0KcmFuZG9tU2FtcGxlUE9TIDwtIHNhbXBsZShtZXJnZWREYXRhTm9EdXBbMjo0MzFdLCAyNSkNCnJhbmRvbVNhbXBsZU5FRyA8LSBzYW1wbGUobWVyZ2VkRGF0YU5vRHVwWzQzMjo0ODVdLCAyNSkNCnJhbmRvbVNhbXBsZSA8LSBjYmluZChyYW5kb21TYW1wbGVQT1MscmFuZG9tU2FtcGxlTkVHLCBtZXJnZWREYXRhTm9EdXAkZW5zZW1ibF9nZW5lX2lkLCBtZXJnZWREYXRhTm9EdXAkSFVHTykNCg0KDQpgYGANCg0KRGVmaW5lIGdyb3VwcyB0byB1c2UgaW4gbm9ybWFsaXphdGlvbg0KYGBge3J9DQoNCnNhbXBsZXMgPC0gZGF0YS5mcmFtZShsYXBwbHkoY29sbmFtZXMocmFuZG9tU2FtcGxlWzE6NTBdKSwgDQogICAgICAgIEZVTj1mdW5jdGlvbih4KXt1bmxpc3Qoc3Ryc3BsaXQoeCwgDQogICAgICAgICAgICAgICAgICAgICAgICBzcGxpdCA9ICJfIikpW2MoMiwxKV19KSkNCmNvbG5hbWVzKHNhbXBsZXMpIDwtIGNvbG5hbWVzKHJhbmRvbVNhbXBsZVsxOjUwXSkNCnJvd25hbWVzKHNhbXBsZXMpIDwtIGMoInBhdGllbnRzIiwiY2VsbF90eXBlIikNCnNhbXBsZXMgPC0gZGF0YS5mcmFtZSh0KHNhbXBsZXMpKQ0KDQpgYGANCg0KDQpBcHBseWluZyBUTU0gdG8gZGF0YQ0KYGBge3J9DQoNCmZpbHRlcmVkX2RhdGFfbWF0cml4IDwtIGFzLm1hdHJpeChyYW5kb21TYW1wbGVbMTo1MF0pDQpyb3duYW1lcyhmaWx0ZXJlZF9kYXRhX21hdHJpeCkgPC0gcmFuZG9tU2FtcGxlJGBtZXJnZWREYXRhTm9EdXAkZW5zZW1ibF9nZW5lX2lkYA0KZCA9IERHRUxpc3QoY291bnRzPWZpbHRlcmVkX2RhdGFfbWF0cml4LCBncm91cD1zYW1wbGVzJGNlbGxfdHlwZSkNCg0KZCA9IGNhbGNOb3JtRmFjdG9ycyhkKQ0KDQpub3JtYWxpemVkX2NvdW50cyA8LSBjcG0oZCkNCiNhZGQgY29sdW1ucyBvZiBlbnNlbWJsIGFuZCBoZ25jIGlkDQoNCm5vcm1hbGl6ZWRfY291bnRfZGF0YSA9IGRhdGEuZnJhbWUobm9ybWFsaXplZF9jb3VudHMpDQpub3JtYWxpemVkX2NvdW50X2RhdGEkZW5zZW1ibF9nZW5lX2lkIDwtIG1lcmdlZERhdGFOb0R1cCRlbnNlbWJsX2dlbmVfaWQNCm5vcm1hbGl6ZWRfY291bnRfZGF0YSRoZ25jX3N5bWJvbCA8LSBtZXJnZWREYXRhTm9EdXAkSFVHTw0KDQoNCiNUaGlzIGlzIGEgZHVwbGljYXRlIGVuc2VtYmwgaWQgdGhhdCBpcyBnaXZpbmcgZXJyb3JzIHdoZW4gcnVubmluZyBjb2RlLg0Kbm9ybWFsaXplZF9jb3VudF9kYXRhIDwtIG5vcm1hbGl6ZWRfY291bnRfZGF0YVstYygxOTAyKSxdDQpgYGANCg0KDQpgYGB7cn0NCm1vZGVsX2Rlc2lnbiA8LSBtb2RlbC5tYXRyaXgofnNhbXBsZXMkY2VsbF90eXBlKzApDQpkIDwtIGVzdGltYXRlRGlzcChkLCBtb2RlbF9kZXNpZ24pDQpgYGANCg0KIyBEaWZmZXJlbnRpYWwgR2VuZSBFeHByZXNzaW9uDQoNCiMjIExJTU1BDQpwLXZhbHVlIGNhbGN1bGF0aW9uIHVzaW5nIExJTU1BDQpgYGB7cn0NCm1vZGVsX2Rlc2lnbiA8LSBtb2RlbC5tYXRyaXgofiBzYW1wbGVzJGNlbGxfdHlwZSApDQpgYGANCg0KYGBge3J9DQoNCmV4cHJlc3Npb25NYXRyaXggPC0gYXMubWF0cml4KG5vcm1hbGl6ZWRfY291bnRfZGF0YVssMTo1MF0pDQpyb3duYW1lcyhleHByZXNzaW9uTWF0cml4KSA8LSANCiAgbm9ybWFsaXplZF9jb3VudF9kYXRhJGVuc2VtYmxfZ2VuZV9pZA0KY29sbmFtZXMoZXhwcmVzc2lvbk1hdHJpeCkgPC0gDQogIGNvbG5hbWVzKG5vcm1hbGl6ZWRfY291bnRfZGF0YSlbMTo1MF0NCm1pbmltYWxTZXQgPC0gRXhwcmVzc2lvblNldChhc3NheURhdGE9ZXhwcmVzc2lvbk1hdHJpeCkNCg0KYGBgDQoNCg0KVGFraW5nIGludG8gYWNjb3VudCBQYXRpZW50IHZhcmlhYmlsaXR5DQpgYGB7cn0NCm1vZGVsX2Rlc2lnbl9wYXQgPC0gbW9kZWwubWF0cml4KA0KICB+IHNhbXBsZXMkcGF0aWVudHMgKyBzYW1wbGVzJGNlbGxfdHlwZSkNCmBgYA0KDQpgYGB7cn0NCmZpdF9wYXQgPC0gbG1GaXQobWluaW1hbFNldCwgbW9kZWxfZGVzaWduX3BhdCkNCmBgYA0KDQoNCmBgYHtyfQ0KZml0Ml9wYXQgPC0gZUJheWVzKGZpdF9wYXQsdHJlbmQ9VFJVRSkNCg0KdG9wZml0X3BhdCA8LSB0b3BUYWJsZShmaXQyX3BhdCwgDQogICAgICAgICAgICAgICAgICAgY29lZj1uY29sKG1vZGVsX2Rlc2lnbl9wYXQpLA0KICAgICAgICAgICAgICAgICAgIGFkanVzdC5tZXRob2QgPSAiQkgiLA0KICAgICAgICAgICAgICAgICAgIG51bWJlciA9IG5yb3coZXhwcmVzc2lvbk1hdHJpeCkpDQojbWVyZ2UgaGduYyBuYW1lcyB0byB0b3BmaXQgdGFibGUNCm91dHB1dF9oaXRzX3BhdCA8LSBtZXJnZShub3JtYWxpemVkX2NvdW50X2RhdGFbLDUxOjUyXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICB0b3BmaXRfcGF0LGJ5Lnk9MCxieS54PTEsYWxsLnk9VFJVRSkNCiNzb3J0IGJ5IHB2YWx1ZQ0Kb3V0cHV0X2hpdHNfcGF0IDwtIG91dHB1dF9oaXRzX3BhdFtvcmRlcihvdXRwdXRfaGl0c19wYXQkUC5WYWx1ZSksXQ0KYGBgDQoNCmBgYHtyfQ0KbGVuZ3RoKHdoaWNoKG91dHB1dF9oaXRzX3BhdCRQLlZhbHVlIDwgMC4wNSkpDQpsZW5ndGgod2hpY2gob3V0cHV0X2hpdHNfcGF0JGFkai5QLlZhbCA8IDAuMDUpKQ0KYGBgDQoNCiMjIFFMRg0KDQpgYGB7cn0NCmQgPSBER0VMaXN0KGNvdW50cz1maWx0ZXJlZF9kYXRhX21hdHJpeCwgZ3JvdXA9c2FtcGxlcyRjZWxsX3R5cGUpDQpgYGANCmBgYHtyfQ0KZCA8LSBlc3RpbWF0ZURpc3AoZCwgbW9kZWxfZGVzaWduX3BhdCkNCmBgYA0KDQpgYGB7cn0NCmZpdCA8LSBnbG1RTEZpdChkLCBtb2RlbF9kZXNpZ25fcGF0KQ0KYGBgDQoNCg0KYGBge3J9DQpxbGYucG9zX3ZzX25lZyA8LSBnbG1RTEZUZXN0KGZpdCwgY29lZj0nc2FtcGxlcyRjZWxsX3R5cGVQT1MnKQ0Ka2FibGUodG9wVGFncyhxbGYucG9zX3ZzX25lZyksIHR5cGU9Imh0bWwiLHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNClAtdmFsdWVzIHdlcmUgY29ycmVjdGVkIHVzaW5nIFF1YXNpbGlrZWxpaG9vZCBtZXRob2QuDQpRdWFzaWxpa2VsaWhvb2QgaXMgYmV0dGVyIGJlY2FjdXNlIGl0IGlzIHRhaWxvcmVkIHRvd2FyZHMgUk5Bc2VxIGRhdGENCg0KYGBge3J9DQpxbGZfb3V0cHV0X2hpdHMgPC0gdG9wVGFncyhxbGYucG9zX3ZzX25lZyxzb3J0LmJ5ID0gIlBWYWx1ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gbnJvdyhub3JtYWxpemVkX2NvdW50X2RhdGEpKQ0KbGVuZ3RoKHdoaWNoKHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KSkNCmxlbmd0aCh3aGljaChxbGZfb3V0cHV0X2hpdHMkdGFibGUkRkRSIDwgMC4wNSkpDQpgYGANCg0KIyBUaHJlc2hvbGRlZCBvdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzDQoNCiMjIFdyaXRlIHRvIGZpbGUgdXByZWd1bGF0ZWQsIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzDQoNCldoaWNoIG9uZXMgYXJlIHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkDQpgYGB7cn0NCmxlbmd0aCh3aGljaChxbGZfb3V0cHV0X2hpdHMkdGFibGUkUFZhbHVlIDwgMC4wNSANCiAgICAgICAgICAgICAmIHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRsb2dGQyA+IDApKQ0KDQpsZW5ndGgod2hpY2gocWxmX291dHB1dF9oaXRzJHRhYmxlJFBWYWx1ZSA8IDAuMDUgDQogICAgICAgICAgICAgJiBxbGZfb3V0cHV0X2hpdHMkdGFibGUkbG9nRkMgPCAwKSkNCmBgYA0KDQpgYGB7cn0NCnFsZl9vdXRwdXRfaGl0c193aXRoZ24gPC0gbWVyZ2UocmFuZG9tU2FtcGxlWyw1MTo1Ml0scWxmX291dHB1dF9oaXRzLCBieS54PTEsIGJ5LnkgPSAwKQ0KI251bWJlciBoaWdoZXIgdGhlIGxvd2VyIHRoZSBwdmFsdWUsIGFuZCBpZiBpdCBpcyB1cHJlZ3VsYXRlZCBudW1iZXIgaXMgcG9zaXRpdmUsIGFuZCBuZWdhdGl2ZSBmb3IgZG93bnJlZ3VsYXRlZA0KcWxmX291dHB1dF9oaXRzX3dpdGhnblssInJhbmsiXSA8LSAtbG9nKHFsZl9vdXRwdXRfaGl0c193aXRoZ24kUFZhbHVlLGJhc2UgPTEwKSAqIHNpZ24ocWxmX291dHB1dF9oaXRzX3dpdGhnbiRsb2dGQykNCnFsZl9vdXRwdXRfaGl0c193aXRoZ24gPC0gcWxmX291dHB1dF9oaXRzX3dpdGhnbltvcmRlcihxbGZfb3V0cHV0X2hpdHNfd2l0aGduJHJhbmspLF0NCnVwcmVndWxhdGVkX2dlbmVzIDwtIHFsZl9vdXRwdXRfaGl0c193aXRoZ24kYG1lcmdlZERhdGFOb0R1cCRIVUdPYFsNCiAgd2hpY2gocWxmX291dHB1dF9oaXRzX3dpdGhnbiRQVmFsdWUgPCAwLjA1IA0KICAgICAgICAgICAgICYgcWxmX291dHB1dF9oaXRzX3dpdGhnbiRsb2dGQyA+IDApXQ0KZG93bnJlZ3VsYXRlZF9nZW5lcyA8LSBxbGZfb3V0cHV0X2hpdHNfd2l0aGduJGBtZXJnZWREYXRhTm9EdXAkSFVHT2BbDQogIHdoaWNoKHFsZl9vdXRwdXRfaGl0c193aXRoZ24kUFZhbHVlIDwgMC4wNSANCiAgICAgICAgICAgICAmIHFsZl9vdXRwdXRfaGl0c193aXRoZ24kbG9nRkMgPCAwKV0NCndyaXRlLnRhYmxlKHg9dXByZWd1bGF0ZWRfZ2VuZXMsDQogICAgICAgICAgICBmaWxlPWZpbGUucGF0aCgiZGF0YSIsInVwcmVndWxhdGVkX2dlbmVzLnR4dCIpLHNlcCA9ICJcdCIsDQogICAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSxjb2wubmFtZXMgPSBGQUxTRSxxdW90ZSA9IEZBTFNFKQ0Kd3JpdGUudGFibGUoeD1kb3ducmVndWxhdGVkX2dlbmVzLA0KICAgICAgICAgICAgZmlsZT1maWxlLnBhdGgoImRhdGEiLCJkb3ducmVndWxhdGVkX2dlbmVzLnR4dCIpLHNlcCA9ICJcdCIsDQogICAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSxjb2wubmFtZXMgPSBGQUxTRSxxdW90ZSA9IEZBTFNFKQ0Kd3JpdGUudGFibGUoeD1kYXRhLmZyYW1lKGdlbmVuYW1lPSBxbGZfb3V0cHV0X2hpdHNfd2l0aGduJGBtZXJnZWREYXRhTm9EdXAkSFVHT2AsRl9zdGF0PSBxbGZfb3V0cHV0X2hpdHNfd2l0aGduJHJhbmspLA0KICAgICAgICAgICAgZmlsZT1maWxlLnBhdGgoImRhdGEiLCJyYW5rZWRfZ2VuZWxpc3QudHh0Iiksc2VwID0gIlx0IiwNCiAgICAgICAgICAgIHJvdy5uYW1lcyA9IEZBTFNFLGNvbC5uYW1lcyA9IEZBTFNFLHF1b3RlID0gRkFMU0UpDQpgYGANCg0KIyBOb24tdGhyZXNob2xkZWQgR2VuZSBzZXQgRW5yaWNobWVudCBBbmFseXNpcw0KDQpgYGB7cn0NCmdtdF91cmwgPSAiaHR0cDovL2Rvd25sb2FkLmJhZGVybGFiLm9yZy9FTV9HZW5lc2V0cy9jdXJyZW50X3JlbGVhc2UvSHVtYW4vc3ltYm9sLyINCiMgbGlzdCBhbGwgdGhlIGZpbGVzIG9uIHRoZSBzZXJ2ZXINCmZpbGVuYW1lcyA9IFJDdXJsOjpnZXRVUkwoZ210X3VybCkNCnRjID0gdGV4dENvbm5lY3Rpb24oZmlsZW5hbWVzKQ0KY29udGVudHMgPSByZWFkTGluZXModGMpDQpjbG9zZSh0YykNCiMgZ2V0IHRoZSBnbXQgdGhhdCBoYXMgYWxsIHRoZSBwYXRod2F5cyBhbmQgZG9lcyBub3QgaW5jbHVkZSB0ZXJtcyBpbmZlcnJlZA0KIyBmcm9tIGVsZWN0cm9uaWMgYW5ub3RhdGlvbnMoSUVBKSBzdGFydCB3aXRoIGdtdCBmaWxlIHRoYXQgaGFzIHBhdGh3YXlzIG9ubHkNCnJ4ID0gZ3JlZ2V4cHIoIig/PD08YSBocmVmPVwiKSguKi5HT0JQX0FsbFBhdGh3YXlzX25vX0dPX2llYS4qLikoLmdtdCkoPz1cIj4pIiwgY29udGVudHMsDQogICAgcGVybCA9IFRSVUUpDQpnbXRfZmlsZSA9IHVubGlzdChyZWdtYXRjaGVzKGNvbnRlbnRzLCByeCkpDQpkZXN0X2dtdF9maWxlIDwtIGZpbGUucGF0aChkYXRhX2RpciwgZ210X2ZpbGUpDQpkb3dubG9hZC5maWxlKHBhc3RlKGdtdF91cmwsIGdtdF9maWxlLCBzZXAgPSAiIiksICJiYWRlcl9sYWIuZ210IikNCmBgYA0KDQpDb25kdWN0IG5vbi10aHJlc2hvbGRlZCBnZW5lIHNldCBlbnJpY2htZW50IGFuYWx5c2lzIHVzaW5nIHRoZSByYW5rZWQgc2V0IG9mIGdlbmVzIGZyb20gQXNzaWdubWVudCAjMi4NCg0KMS4gV2hhdCBtZXRob2QgZGlkIHlvdSB1c2U/IFdoYXQgZ2VuZXNldHMgZGlkIHlvdSB1c2U/IE1ha2Ugc3VyZSB0byBzcGVjaWZ5IHZlcnNpb25zIGFuZCBjaXRlIHlvdXIgbWV0aG9kcy4NCkkgdXNlZCB0aGUgR1NFQSBkZXNrdG9wIGFwcGxpY2F0aW9uIHRvIHJ1biBHU0VBICBTdWJyYW1hbmlhbiwgVGFtYXlvLCBldCBhbC4gKDIwMDUsIFBOQVMpIGFuZCBNb290aGEsIExpbmRncmVuLCBldCBhbC4gKDIwMDMsIE5hdHVyZSBHZW5ldGljcykuIA0KSSB1c2VkIHRoZSBnZW5lc2V0cyBmcm9tIHRoZSBiYWRlciBsYWIgZXh0cmFjdGVkIGZyb20gdGhlIGNvZGUgYWJvdmUgSSB1c2VkLiBPciBpdCBjYW4gYmUgcmV0cmlldmVkIGZyb20gaGVyZSBodHRwOi8vZG93bmxvYWQuYmFkZXJsYWIub3JnL0VNX0dlbmVzZXRzL2N1cnJlbnRfcmVsZWFzZS9IdW1hbi9zeW1ib2wvLg0KMi4gU3VtbWFyaXplIHlvdXIgZW5yaWNobWVudCByZXN1bHRzLg0KU0FScy1Db1YtMiBwb3NpdGl2ZSBzYW1wbGVzOg0KNDk2NSAvIDYwNzQgZ2VuZSBzZXRzIGFyZSB1cHJlZ3VsYXRlZCBpbiBwaGVub3R5cGUgbmFfcG9zDQo0NDIgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudCBhdCBGRFIgPCAyNSUNCjQxMCBnZW5lIHNldHMgYXJlIHNpZ25pZmljYW50bHkgZW5yaWNoZWQgYXQgbm9taW5hbCBwdmFsdWUgPCAxJQ0KNjYyIGdlbmUgc2V0cyBhcmUgc2lnbmlmaWNhbnRseSBlbnJpY2hlZCBhdCBub21pbmFsIHB2YWx1ZSA8IDUlDQpUb3AgZ2VuZS1zZXQ6IEhBTExNQVJLX0lOVEVSRkVST05fQUxQSEFfUkVTUE9OU0UlTVNJR0RCSEFMTE1BUkslSEFMTE1BUktfSU5URVJGRVJPTl9BTFBIQV9SRVNQT05TRQ0KTnVtYmVyIG9mIGdlbmVzIGluIGxlYWRpbmcgZWRnZTogODANClRvcCBnZW5lIGFzc29jaWF0ZWQ6IENYQ0wxMQ0KDQpTQVJzLUNvVi0yIG5lZ2F0aXZlIHNhbXBsZXM6DQoxMTA5IC8gNjA3NCBnZW5lIHNldHMgYXJlIHVwcmVndWxhdGVkIGluIHBoZW5vdHlwZSBuYV9uZWcNCjI3NCBnZW5lIHNldHMgYXJlIHNpZ25pZmljYW50bHkgZW5yaWNoZWQgYXQgRkRSIDwgMjUlDQoxOTYgZ2VuZSBzZXRzIGFyZSBzaWduaWZpY2FudGx5IGVucmljaGVkIGF0IG5vbWluYWwgcHZhbHVlIDwgMSUNCjI3NiBnZW5lIHNldHMgYXJlIHNpZ25pZmljYW50bHkgZW5yaWNoZWQgYXQgbm9taW5hbCBwdmFsdWUgPCA1JQ0KVG9wIGdlbmUtc2V0OiBFTkVSR1kgREVSSVZBVElPTiBCWSBPWElEQVRJT04gT0YgT1JHQU5JQyBDT01QT1VORFMlR09CUCVHTzowMDE1OTgwDQpOdW1iZXIgb2YgZ2VuZXMgaW4gbGVhZGluZyBlZGdlOiAxNjUNClRvcCBnZW5lIGFzc29jaWF0ZWQ6IFRFRk0NCjMuIEhvdyBkbyB0aGVzZSByZXN1bHRzIGNvbXBhcmUgdG8gdGhlIHJlc3VsdHMgZnJvbSB0aGUgdGhyZXNob2xkZWQgYW5hbHlzaXMgaW4gQXNzaWdubWVudCAjMi4gQ29tcGFyZSBxdWFsaXRhdGl2ZWx5LiBJcyB0aGlzIGEgc3RyYWlnaHQgZm9yd2FyZCBjb21wYXJpc29uPyBXaHkgb3Igd2h5IG5vdD8NCkZvciB0aGUgdXByZWd1bGF0ZWQgZ2VuZXMgdGhlIHRvcCByZXN1bHRzIGFyZSBuZWdhdGl2ZSByZWd1bGF0aW9uIG9mIHZpcmFsIGdlbm9tZSByZXBsaWNhdGlvbiwgbmVnYXRpdmUgcmVndWxhdGlvbiBvZiB2aXJhbCBwcm9jZXNzLCByZXNwb25zZSB0byB0eXBlIElJIGludGVyZmVyb24uIGRvd25yZWd1bGF0ZWQgd2UgZ290IGN5dG9wbGFzbWljIHRyYW5zbGF0aW9uLCBwb3NpdGl2ZSByZWd1bGF0aW9uIG9mIHJlc3BpcmF0b3J5IGJ1cnN0LCBhbmQgaW50ZXJtZWRpYXRlIGZpbGFtZW50LWJhc2VkIHByb2Nlc3MuIEkgaGFkIHRvbyBtYW55IGdlbmVzIHNvIEkgY291bGRuJ3QgcnVuIGFsbCB0aGUgZ2VuZXMgYXQgb25jZSBmb3IgbXkgd2hvbGUgbGlzdC4gRm9yIHVwcmVndWxhdGVkIGluIHRocmVzaG9sZGVkIGFuZCBub24tdGhyZXNob2xkZWQgdGhleSBhbGlnbiBhIGJpdCB0b2dldGhlciBieSBoYXZpbmcgaW50ZXJmZXJvbiByZWxhdGVkIHBhdGh3YXkgcmVzdWx0cy4gT3RoZXIgdGhlbiB0aGF0IHRoZXkgZG9uJ3Qgc2VlbSB0byBiZSBzaW1pbGFyLiBBIGNvbW1vbiBwYXRod2F5IGluIGRvd25yZWd1bGF0ZWQgYW5kIGFuZCBhbGwgb2YgdGhlIGdlbmVzIGZvciB0aHJlc2hvbGRlZCB3YXMgYSBwYXRod2F5IHJlbGF0ZWQgdG8gY3l0b3BsYXNtaWMuIEhvd2V2ZXIgaW4gbm9uIHRocmVzaG9sZGVkIHRoZXJlIHdlcmUgY3l0b3BsYXNtaWMgcmVsYXRlZCBwYXRod2F5cyBidXQgd2VyZSB2ZXJ5IGxvdyBpbiB0aGUgbGlzdC4gSXQgaXMgbm90IGEgc3RyYWlnaHQgZm9yd2FyZCBjb21wYXJpc29uIHRoZXkgYm90aCBoYXZlIGRpZmZlcmVudCB2YWx1ZXMgYXMgYW5hbHlzaXMuIFRoZSB0aHJlc2hvbGVkIGNvdWxkIGJlIG1vcmUgc2Vuc2l0aXZlIHdoaWxlIHRoZSBub24tdGhyZXNob2xkZWQgYmUgbW9yZSBnZW5lcmFsLg0KDQoNCg0KDQpVc2luZyB5b3VyIHJlc3VsdHMgZnJvbSB5b3VyIG5vbi10aHJlc2hvbGRlZCBnZW5lIHNldCBlbnJpY2htZW50IGFuYWx5c2lzIHZpc3VhbGl6ZSB5b3VyIHJlc3VsdHMgaW4gQ3l0b3NjYXBlLg0KDQpyZWQgLSB1cHJlZ3VsYXRlZCBmcm9tIG5lZyB0byBwb3MsIGJsdWUgLSBkb3ducmVndWxhdGVkIGluIHBvc2l0aXZlIGNvdmlkMTkgcGF0aWV0bnMgY29tcGFyZWQgdG8gbmVnYXRpdmUgcGF0aWVudHMuIA0KcmFua2VkIGxpc3QgPSBkZXBlbmRpbmcgb24gdGhlIGV4cHJlc3Npb24gb2YgYSBnZW5lIGluIHBvcyBjb21wYXJlZCB0byBuZWcNCg0KIyMgMS4gDQojIyMgQ3JlYXRlIGFuIGVucmljaG1lbnQgbWFwIC0gaG93IG1hbnkgbm9kZXMgYW5kIGhvdyBtYW55IGVkZ2VzIGluIHRoZSByZXN1bHRpbmcgbWFwPw0KMzc5IE5vZGVzDQoxNTExIEVkZ2VzDQoNCiMjIyBXaGF0IHRocmVzaG9sZHMgd2VyZSB1c2VkIHRvIGNyZWF0ZSB0aGlzIG1hcD8gDQpGRFIgcS12YWx1ZSBjdXRvZmY6IDAuMQ0KQW5hbHlzaXMgVHlwZTogR1NFQQ0KTm9kZSBjdXRvZmY6IDAuMSANCkVkZ2UgY3V0b2ZmOiAwLjM3NQ0KDQojIyMgTWFrZSBzdXJlIHRvIHJlY29yZCBhbGwgdGhyZXNob2xkcy4gSW5jbHVkZSBhIHNjcmVlbnNob3Qgb2YgeW91ciBuZXR3b3JrIHByaW9yIHRvIG1hbnVhbCBsYXlvdXQuDQogIVtGaWd1cmU6IFNjcmVlbnNob3Qgb2YgbmV0d29yayBwcmlvciB0byBtYW51YWwgbGF5b3V0XSguL2ZpZ3VyZS9wcmlvcnRvbWFudWFsLnBuZykNCg0KIyMjIDIuIEFubm90YXRlIHlvdXIgbmV0d29yayAtIHdoYXQgcGFyYW1ldGVycyBkaWQgeW91IHVzZSB0byBhbm5vdGF0ZSB0aGUgbmV0d29yay4gSWYgeW91IGFyZSB1c2luZyB0aGUgZGVmYXVsdCBwYXJhbWV0ZXJzIG1ha2Ugc3VyZSB0byBsaXN0IHRoZW0gYXMgd2VsbC4NClVzZWQgdGhlIGF1dG8gYW5ub3RhdGUgYXBwbGljYXRpb24gaW4gY3l0b3NjYXBlLiANCkNsdXN0ZXIgYWxnb3JpdGhtOiBNQ0wgQ2x1c3Rlcg0KTGFiZWwgQ29sdW1uOiBHU19ERVNDUg0KTGFiZWwgQWxnb3JpdGhtOiBXb3JkQ2xvdWQ6IEFkamFjZW50IFdvcmRzKGRlZmF1bHQpDQpNYXggd29yZHMgcGVyIGxhYmVsOiAzDQpNaW5pbXVtIHdvcmQgb2NjdXJyZW5jZTogMQ0KQWRqYWNlbnQgd29yZCBib251czogOA0KQm9yZGVyIFdpZHRoOiAzDQpPcGFjaXR5OiAyMCUNCkZvbnQgU2NhbGU6IDIwJQ0KDQoNCiAhW0ZpZ3VyZTogQW5ub3RhdGVkIG5ldHdvcmtdKC4vZmlndXJlL2Fubm90YXRlZG5ldHdvcmsucG5nKQ0KDQojIyMgMy4gTWFrZSBhIHB1YmxpY2F0aW9uIHJlYWR5IGZpZ3VyZSAtIGluY2x1ZGUgdGhpcyBmaWd1cmUgd2l0aCBwcm9wZXIgbGVnZW5kcyBpbiB5b3VyIG5vdGVib29rLg0KDQoNCiMjIyA0LiBDb2xsYXBzZSB5b3VyIG5ldHdvcmsgdG8gYSB0aGVtZSBuZXR3b3JrLiBXaGF0IGFyZSB0aGUgbWFqb3IgdGhlbWVzIHByZXNlbnQgaW4gdGhpcyBhbmFseXNpcz8gRG8gdGhleSBmaXQgd2l0aCB0aGUgbW9kZWw/IEFyZSB0aGVyZSBhbnkgbm92ZWwgcGF0aHdheXMgb3IgdGhlbWVzPw0KICFbRmlndXJlOiBDb2xsYXBzZWRdKC4vZmlndXJlL2NvbGxhcHNlZC5wbmcpDQpNYWpvciB0aGVtZXMgcHJlc2VudDoNClVwcmVndWxhdGVkOg0KLSBHUENSUyBSaG9kb3BzaW4gbGlnYW5kDQotIENoZW1va2luZSBNaWdyYXRpb24gY2hlbW90YXhpcw0KLSBDZWxsdWxhciByZXNwb25zZSBuZWNyb3Npcw0KLSB0eXBlIElJIGludGVyZmVyb24NCi0gTWlncmF0aW9uIG1vbm9jeXRlIGNoZW1vdGF4aXMNCi0gU3VyZmFjZSByZWNlcHRvciBwYXR0ZXJuDQoNCkRvd25yZWd1bGF0ZWQ6IA0KLSBnbHVjb25lb2dlbmVzaXMgZ2x5Y29seXNpcw0KLSBzdXBlcnBhdGh3YXkgd2FyYnVyZyBlZmZlY3QNCi0gc3JwIHByb3RlaW4gc3ludGhlc2lzIA0KDQpQcmVzZW50IHlvdXIgcmVzdWx0cyB3aXRoIHRoZSB1c2Ugb2YgdGFibGVzIGFuZCBzY3JlZW5zaG90cy4gQWxsIGZpZ3VyZXMgc2hvdWxkIGhhdmUgYXBwcm9wcmlhdGUgZmlndXJlIGxlZ2VuZHMuDQoNCklmIHVzaW5nIGZpZ3VyZXMgY3JlYXRlIGEgZmlndXJlcyBkaXJlY3RvcnkgaW4geW91ciByZXBvIGFuZCBtYWtlIHN1cmUgYWxsIHJlZmVyZW5jZXMgdG8gdGhlIGZpZ3VyZXMgYXJlIHJlbGF0aXZlIGluIHlvdXIgUm1hcmtkb3duIG5vdGVib29rLg0KDQoNClRoZSBtb3N0IGltcG9ydGFudCBhc3BlY3Qgb2YgdGhlIGFuYWx5c2lzIGlzIHJlbGF0aW5nIHlvdXIgcmVzdWx0cyBiYWNrIHRvIHRoZSBpbml0aWFsIGRhdGEgYW5kIHF1ZXN0aW9uLg0KDQoxLiBEbyB0aGUgZW5yaWNobWVudCByZXN1bHRzIHN1cHBvcnQgY29uY2x1c2lvbnMgb3IgbWVjaGFuaXNtIGRpc2N1c3NlZCBpbiB0aGUgb3JpZ2luYWwgcGFwZXI/IEhvdyBkbyB0aGVzZSByZXN1bHRzIGRpZmZlciBmcm9tIHRoZSByZXN1bHRzIHlvdSBnb3QgZnJvbSBBc3NpZ25tZW50ICMyIHRocmVzaG9sZGVkIG1ldGhvZHMuXCANCg0KVGhpcyBpcyBhIHF1b3RhdGlvbiB0YWtlbiBmcm9tIHRoZSBvcmlnaW5hbCBwYXBlciAiU0FSUy1Db1YtMiBpbmR1Y2VkIGEgc3Ryb25nIGFudGl2aXJhbCByZXNwb25zZSB3aXRoIHVwLXJlZ3VsYXRpb24gb2YgYW50aXZpcmFsIGZhY3RvcnMgc3VjaCBhcyBPQVMxLTMgYW5kIElGSVQxLTMgYW5kIFQgaGVscGVyIHR5cGUgMSAoVGgxKSBjaGVtb2tpbmVzIENYQ0w5LzEwLzExLCBhcyB3ZWxsIGFzIGEgcmVkdWN0aW9uIGluIHRyYW5zY3JpcHRpb24gb2Ygcmlib3NvbWFsIHByb3RlaW5zIiBbQGxpZWJlcm1hbjIwMjB2aXZvXS4gVGhleSBoYXZlIGZvdW5kIHVwLXJlZ3VsYXRpb24gaW4gbnVtYmVyIG9mIGdlbmVzLiBUaGUgbGFyZ2VzdCBjb2xsYXBzZWQgdGhlbWUgd2l0aCA3MjkgZ2VuZXMgdGhlIEdQQ1JTIFJob2RvcHNpbiBsaWdhbmQgaGFzIHR3byB2ZXJ5IGxhcmdlIHBhdGh3YXlzIG5hbWVkIHRoZSBHUENSIGxpZ2FuZCBiaW5kaW5nLCBhbmQgdGhlIENMQVNTIEEgMSAoUkhPRE9QU0lOLUxJS0UgUkVDRVBUT1JTKS4gQm90aCBvZiB0aGVzZSBnZW5lLXNldHMgaGF2ZSBhdCB0aGUgdG9wIG9mIHRoZWlyIGxlYWRpbmcgZWRnZSB0aGUgQ1hDTCAxMC8xMS8xMyBzaW1pbGFyIHRvIHRoZSBwYXBlciB3aGVyZSB0aGV5IGhhZCB1cC1yZWd1bGF0aW9uIGluIHRoZSBDWENMIDkvMTAvMTEuIEluIHRoaXMgc2Vuc2UgdGhlIGVucmljaG1lbnQgcmVzdWx0cyBzdXBwb3J0IGNvbmNsdXNpb25zIG1hZGUgaW4gdGhlIG9yaWdpbmFsIHBhcGVyLiBBbm90aGVyIGV4YW1wbGUgaXMgdGhlIGNoZW1va2luZSBtaWdyYXRpb24gY2hlbW90YXhpcy4gSW4gdGhpcyBtYWpvciB0aGVtZSB0aGVyZSBhcmUgZ2VuZS1zZXRzIGludm9sdmVkIGluIHBhdGh3YXlzIHN1Y2ggYXMgdGhlIHJlc3BvbnNlIHRvIHR5cGUgSUkgaW50ZXJmZXJvbiwgY2VsbHVsYXIgcmVzcG9uc2UgdG8gdHlwZSBJSSBpbnRlcmZlcm9uLCAuIEluIHRoZSBvcmlnaW5hbCBwYXBlciB0aGV5IG1lbnRpb24gdGhhdCBhcyB2aXJhbCBsb2FkIGluY3JlYXNlZCB0aGUgZXhwcmVzc2lvbiBvZiBpbnRlcmZlcm9uLXJlc3BvbnNpdmUgZ2VuZXMgd2VudCB1cC4gQm90aCBvZiB0aGUgdHdvIHRoZW1lcyBtZW50aW9uZWQgYXJlIHVwLXJlZ3VsYXRlZCBnZW5lLXNldHMuIEl0IHNlZW1zIHRoYXQgdGhlIGVucmljaG1lbnQgcmVzdWx0cyBzdXBwb3J0IHRoZSBjb25jbHVzaW9uIGluIHRoZSBvcmlnaW5hbCBwYXBlci4gXCANCkNvbXBhcmluZyBmcm9tIEEyIHRocmVzaG9sZCBtZXRob2RzIGluIHRoZSB1cHJlZ3VsYXRlZCBhbmFseXNpcyBmb3IgR08gdXNpbmcgZzpwcm9maWxlciB3ZSBhbHNvIGhhZCByZXN1bHRzIHN1Y2ggYXMgcmVzcG9uc2UgdG8gdHlwZSBJSSBpbnRlcmZlcm9uLCBhbmQgY2VsbHVsYXIgcmVzcG9uc2UgdG8gdHlwZSBJSSBpbnRlcmZlcm9uLiBIb3dldmVyIHdlIGRvIG5vdCBzZWUgYSBsb3Qgb2YgZ2VuZS1zZXRzIGluIHRoZSB1cC1yZWd1bGF0ZWQgc2VjdGlvbiBmb3IgY2hlbW9raW5lIHJlbGF0ZWQgcGF0aHdheXMuIFwgDQoNCkZvciBkb3duIHJlZ3VsYXRlZCBnZW5lLXNldHMgZm9yIG91ciBuZXR3b3JrIHJlc3VsdHMgZnJvbSBHU0VBIHNob3dzIGEgbWFqb3IgdGhlbWUgY2FsbGVkIHNycCBwcm90ZWluIHN5bnRoZXNpcy4gSW4gdGhpcyB3ZSBoYXZlIGdlbmVzZXRzIHN1Y2ggYXMgdGhlIGN5dG9wbGFzbWljIHRyYW5zbGF0aW9uLiBUaGlzIGdlbmUtc2V0IGlzIHRoZSBsYXJnZXN0IGdlbmUtc2V0IGluc2lkZSBzcnAgcHJvdGVpbiBzeW50aGVzaXMgYW5kIGl0IGlzIGFsc28gdGhlIHRvcCByZXN1bHQgZm9yIGRvd24gcmVndWxhdGVkIGdlbmVzIGdlbmUtc2V0IGZvciBnOnByb2ZpbGVyIHVzaW5nIEdPIGFubm90YXRpb24uIFRoZXJlIGFyZSBldmlkZW50IHNpbWlsYXJpdGllcyBidXQgbG9va2luZyBhdCB0aGUgcmVzdCBvZiB0aGUgZ3JhcGggZWFjaCBhbmFseXNpcyBnaXZlIHJlc3VsdHMgdGhhdCBlYWNoIG90aGVyIGRvIG5vdCBoYXZlLiBcIA0KDQoNCg0KMi4gQ2FuIHlvdSBmaW5kIGV2aWRlbmNlLCBpLmUuIHB1YmxpY2F0aW9ucywgdG8gc3VwcG9ydCBzb21lIG9mIHRoZSByZXN1bHRzIHRoYXQgeW91IHNlZS4gSG93IGRvZXMgdGhpcyBldmlkZW5jZSBzdXBwb3J0IHlvdXIgcmVzdWx0Pw0KSW4gYSBwYXBlciB0aGV5IHN0YXRlIHRoYXQgU0FSUy1Db1YtMiBpbmZlY3RlZCB0aHlyb2lkIGdsYW5kIGFjdGl2YXRlZCB0aGUgaW50ZXJmZXJvbiBwYXRod2F5cyBhbGlnbmluZyB3aXRoIG91ciByZXN1bHRzIGluIHRoZSB1cHJlZ3VsYXRpb24uIFtAaW50ZXJmZXJvbl0NCg0KDQpVc2luZyB5b3VyIG5ldHdvcmtzIGFuZCByZXN1bHRzIGZyb20gdGhlIHByZXZpb3VzIHNlY3Rpb24gYWRkIG9uZSBvZiB0aGUgZm9sbG93aW5nOg0KMS4gQWRkIGEgcG9zdCBhbmFseXNpcyB0byB5b3VyIG1haW4gbmV0d29yayB1c2luZyBzcGVjaWZpYyB0cmFuc2NyaXB0aW9uIGZhY3RvcnMsIG1pY3JvUk5BcyBvciBkcnVncy4gSW5jbHVkZSB0aGUgcmVhc29uIHdoeSB5b3UgY2hvc2UgdGhlIHNwZWNpZmljIG1pUnMsIFRGcyBvciBkcnVncyAoaS5lIHB1YmxpY2F0aW9ucyBpbmRpY2F0aW5nIHRoYXQgdGhleSBtaWdodCBiZSByZWxhdGVkIHRvIHlvdXIgbW9kZWwpLiBXaGF0IGRvZXMgdGhpcyBwb3N0IGFuYWx5c2lzIHNob3c/DQoyLCBDaG9vc2UgYSBzcGVjaWZpYyBwYXRod2F5IG9yIHRoZW1lIHRvIGludmVzdGlnYXRlIGluIG1vcmUgZGV0YWlsLiBXaHkgZGlkIHlvdSBjaG9vc2UgdGhpcyBwYXRod2F5IG9yIHRoZW1lPyBTaG93IHRoZSBwYXRod2F5IG9yIHRoZW1lIGFzIGEgZ2VuZSBuZXR3b3JrIG9yIGFzIGEgcGF0aHdheSBkaWFncmFtLiBBbm5vdGF0ZSB0aGUgbmV0d29yayBvciBwYXRod2F5IHdpdGggeW91ciBvcmlnaW5hbCBsb2cgZm9sZCBleHByZXNzaW9uIHZhbHVlcyBhbmQgcC12YWx1ZXMgdG8gc2hvdyBob3cgaXQgaXMgZWZmZWN0ZWQgaW4geW91ciBtb2RlbC4gKEhpbnQ6IGlmIHRoZSB0aGVtZSBvciBwYXRod2F5IGlzIG5vdCBmcm9tIGRhdGFiYXNlIHRoYXQgaGFzIGRldGFpbGVkIG1lY2hhbmlzdGljIGluZm9ybWF0aW9uIGxpa2UgUmVhY3RvbWUgeW91IGNhbiB1c2UgYXBwcyBsaWtlIEdlbmVNQU5JQSBvciBTdHJpbmcgdG8gYnVpbGQgdGhlIHRoZSBpbnRlcmFjdGlvbiBuZXR3b3JrLikNCjMuIFNvbWV0aW1lcyB0aGUgbW9zdCBpbnRlcmVzdGluZyBpbmZvcm1hdGlvbiBpcyB0aGUgZ2VuZSB0aGF0IGhhcyBubyBpbmZvcm1hdGlvbi4gSW4gdGhpcyB0eXBlIG9mIHBhdGh3YXkgYW5hbHlzaXMgd2UgY2FuIG9ubHkgZGlzY292ZXIgd2hhdCB3ZSBoYXZlIGFscmVhZHkgZGVzY3JpYmVkIHByZXZpb3VzbHkgaW4gdGhlIGxpdGVyYXR1cmUgb3IgcGF0aHdheSBkYXRhYmFzZXMuIE9mdGVuIHBhdGh3YXlzIGZvdW5kIGluIG9uZSBkaXNlYXNlIGFyZSBhcHBsaWNhYmxlIHRvIG90aGVyIGRpc2Vhc2VzIHNvIHRoaXMgdGVjaG5pcXVlIGNhbiBiZSB2ZXJ5IGhlbHBmdWwuIEl0IGlzIGltcG9ydGFudCB0byBoaWdobGlnaHQgYW55IGdlbmVzIHRoYXQgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGluIHlvdXIgbW9kZWwgYnV0IGFyZSBub3QgYW5ub3RhdGVkIHRvIGFueSBwYXRod2F5cy4gV2UgcmVmZXIgdG8gdGhpcyBzZXQgb2YgZ2VuZXMgYXMgdGhlIGRhcmsgbWF0dGVyLg0KSW5jbHVkZSBhIGhlYXRtYXAgb2YgYW55IHNpZ25pZmljYW50IGdlbmVzIHRoYXQgYXJlIG5vdCBhbm5vdGF0ZWQgdG8gYW55IG9mIHRoZSBwYXRod2F5cyByZXR1cm5lZCBpbiB0aGUgZW5yaWNobWVudCBhbmFseXNpcy4NCkluY2x1ZGUgYSBoZWF0bWFwIG9mIGFueSBzaWduaWZpY2FudCBnZW5lcyB0aGF0IGFyZSBub3QgYW5ub3RhdGVkIHRvIGFueSBwYXRod2F5cyBpbiBlbnRpcmUgc2V0IG9mIHBhdGh3YXlzIHVzZWQgZm9yIHRoZSBhbmFseXNpcy4NCg0KI1JlZmVyZW5jZXM=